package com.xliang.spider.version03.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xliang.spider.util.CommonEnum;
import com.xliang.spider.util.ConnectionUtil;
import com.xliang.spider.util.CookiesUtil;
import com.xliang.spider.util.HttpUtil;
import com.xliang.spider.version03.dao.SpiderScanCourseDao;
import com.xliang.spider.version03.pojo.CourseEntity;
import com.xliang.spider.version03.service.SpiderScanCourseService;
import org.apache.log4j.Logger;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ${DESCRIPTION}
 *
 * @author xiongl
 * @create 2016-06-14 10:18
 */
@Service
public class SpiderScanCourseServiceImpl implements SpiderScanCourseService
{
    private static Logger logger = Logger.getLogger(SpiderScanCourseServiceImpl.class);
    
    @Resource
    private SpiderScanCourseDao spiderScanCourseDao;
    
    @Override
    public CourseEntity findCourse(CourseEntity ce)
        throws Exception
    {
        return spiderScanCourseDao.findCourse(ce);
    }
    
    @Override
    public boolean insertCourse(CourseEntity ce)
        throws Exception
    {
        return spiderScanCourseDao.insertCourse(ce) == CommonEnum.COMMON_IS.YES.getValue();
    }
    
    @Override
    public boolean updateCourse(CourseEntity ce)
        throws Exception
    {
        return spiderScanCourseDao.updateCourse(ce) == CommonEnum.COMMON_IS.YES.getValue();
    }
    
    @Override
    public void scanCourse()
        throws Exception
    {
        int page = 1;
        Map<String, String> params = new HashMap<>();
        params.put("type", "1");
        while (true)
        {
            params.put("page", page + "");
            JSONObject response = HttpUtil.httpPost("http://ke.jikexueyuan.com/xilie/more", params);
            int code = response.getIntValue("code");
            String msg = response.getString("msg");
            if (code == 200 && msg.equals("ok"))
            {
                JSONObject data = response.getJSONObject("data");
                int is_end = data.getIntValue("is_end");
                if (is_end == 1)
                {
                    logger.info("课程加载完毕");
                    break;
                }
                JSONArray info = data.getJSONArray("info");
                for (Object item : info)
                {
                    JSONObject object = (JSONObject)item;
                    String title = object.getString("title");
                    int id = object.getIntValue("id");
                    logger.info("++++++++++++++++++++++++++++++++++++开始解析课程：" + title + "++++++++++++++++++++++++++++++++++++");
                    getLessons(title, id);
                }
                page++;
            }
            else
            {
                logger.info(String.format("课程加载异常，code=%d，msg=%s", code, msg));
            }
        }
    }
    
    @Override
    public boolean downLoadCourse(String path)
        throws Exception
    {
        List<CourseEntity> coursies = spiderScanCourseDao.findCourseListByStatus(CommonEnum.COURSE_STATUS.ZERO.getValue());
        for (CourseEntity ce : coursies)
        {
            if (ce.getUrl().endsWith(".mp4"))
            {
                String filePath = path + ce.getCourseName() + "\\";
                File file = new File(filePath);
                if (!file.exists())
                {
                    file.mkdirs();
                }
                String fileName = ce.getChapterName() + "_" + ce.getPartName() + ".mp4";
                if (HttpUtil.downLoadRemoteFile(ce.getUrl(), file.getAbsolutePath(), fileName))
                {
                    ce.setStatus(CommonEnum.COURSE_STATUS.SUCCESS.getValue());
                    logger.info("视频下载成功：" + fileName);
                }
                else
                {
                    ce.setStatus(CommonEnum.COURSE_STATUS.FAIL.getValue());
                    logger.info("视频下载失败：" + fileName);
                }
                spiderScanCourseDao.updateCourse(ce);
            }
            else
            {
                logger.info("非mp4文件，跳过。。。");
            }
        }
        return false;
    }
    
    public void getLessons(String courseName, int courseId)
        throws Exception
    {
        Document document = ConnectionUtil.getConnection("http://ke.jikexueyuan.com/xilie/" + courseId).get();
        Elements lessonItems = document.getElementsByClass("lesson-item");
        for (Element item : lessonItems)
        {
            String lessonUrl = item.getElementsByAttribute("jktag").first().attr("href");
            String lessonTitle = item.getElementsByClass("title").first().html();
            getLessonItem(courseName, courseId, lessonTitle, lessonUrl);
        }
    }
    
    public void getLessonItem(String courseName, int courseId, String lessonTitle, String lessonUrl)
        throws Exception
    {
        Document document = ConnectionUtil.getConnection(lessonUrl).cookies(CookiesUtil.createJKCookies()).get();
        Elements lessons = document.getElementsByClass("lesson-box").first().select("h2>a");
        for (Element element : lessons)
        {
            String title = element.html();
            String url = element.attr("href");
            CourseEntity ce = new CourseEntity(courseId, courseName, lessonTitle, title, getVideoUrl(url));
            ce.getCourseName()
                .replaceAll("：", "")
                .replaceAll(":", "")
                .replaceAll("“", "")
                .replaceAll("”", "")
                .replaceAll("’", "")
                .replaceAll("。", "")
                .replaceAll("\"", "")
                .replaceAll("\\\\", "")
                .replaceAll("/", "、");
            ce.getChapterName()
                .replaceAll("：", "")
                .replaceAll(":", "")
                .replaceAll("“", "")
                .replaceAll("”", "")
                .replaceAll("’", "")
                .replaceAll("。", "")
                .replaceAll("\"", "")
                .replaceAll("\\\\", "")
                .replaceAll("/", "、");
            ce.getPartName()
                .replaceAll("：", "")
                .replaceAll(":", "")
                .replaceAll("“", "")
                .replaceAll("”", "")
                .replaceAll("’", "")
                .replaceAll("。", "")
                .replaceAll("\"", "")
                .replaceAll("\\\\", "")
                .replaceAll("/", "、");
            CourseEntity exist = findCourse(ce);
            if (exist == null)
            {
                if (insertCourse(ce))
                {
                    logger.info(String.format("新增视频：%s=%s", ce.getChapterName() + "_" + ce.getPartName(), ce.getUrl()));
                }
                else
                {
                    logger.error(String.format("新增视频失败：%s=%s", ce.getChapterName() + "_" + ce.getPartName(), ce.getUrl()));
                }
            }
            else
            {
                if (exist.getStatus() != CommonEnum.COURSE_STATUS.SUCCESS.getValue())
                {
                    exist.setStatus(CommonEnum.COURSE_STATUS.ZERO.getValue());
                    exist.setUrl(ce.getUrl());
                    if (updateCourse(exist))
                    {
                        logger.info(String.format("更新视频：%s=%s", ce.getChapterName() + "_" + ce.getPartName(), ce.getUrl()));
                    }
                }
            }
        }
    }
    
    public String getVideoUrl(String videoUrl)
    {
        String url = videoUrl;
        try
        {
            Document document = ConnectionUtil.getConnection(videoUrl).cookies(CookiesUtil.createJKCookies()).get();
            Element video = document.getElementsByTag("video").select("source").first();
            url = video.attr("src");
        }
        catch (Exception e)
        {
            logger.error("获取视频地址失败", e);
        }
        return url;
    }
}
